import { Node, Vec3 } from 'cc';
import { Timer } from 'db://app-game/core/common/timer/Timer';
import { Vec3Util } from 'db://app-game/core/utils/Vec3Util';
import { ecs } from 'db://app-game/libs/ecs/ECS';

@ecs.register('MoveTo')
export class MoveToComp extends ecs.Comp {
  /** 移动节点 */
  node: Node = null!;
  /** 移动方向 */
  velocity: Vec3 = new Vec3(0, 0, 0);
  /** 移动速度 (每秒移动的像素距离)*/
  speedOfMove: number = 0;
  /** 目标实体ECS编号、目标位置 */
  target: Vec3 | Node | null = null;
  /** 坐标标（默认本地坐标） */
  ns: number = Node.NodeSpace.LOCAL;
  /** 偏移距离 */
  offset: number = 0;
  /** 偏移向量 */
  offsetVector: Vec3 | null = null;
  /** 移动完成回调 */
  onComplete: Function | null = null;
  /** 距离变化时 */
  onChange: Function | null = null;
  reset(entity: ecs.Entity): void {
    this.ns = Node.NodeSpace.LOCAL;
    this.offset = 0;
    this.target = null;
    this.offsetVector = null;
    this.onComplete = null;
    this.onChange = null;
  }
}

/** 变量移动到组件 */
@ecs.register('VariableMoveTo')
export class VariableMoveToComponent extends ecs.Comp {
  /** 延时触发器 */
  timer: Timer = new Timer();
  /** 终点备份 */
  end: Vec3 | null = null;
  /** 目标位置 */
  target!: Vec3;

  reset() {
    this.end = null;
    this.timer.reset();
    this.target = null!;
  }
}

/** 跟踪移动到目标位置 */
@ecs.register('MoveTo')
export class MoveToSystem
  extends ecs.ComblockSystem<ecs.Entity>
  implements ecs.IEntityEnterSystem, ecs.IEntityRemoveSystem, ecs.ISystemUpdate
{
  filter(): ecs.IMatcher {
    return ecs.allOf(MoveToComp);
  }

  entityEnter(entity: ecs.Entity): void {
    entity.add(VariableMoveToComponent);
  }

  entityRemove(entity: ecs.Entity): void {
    entity.remove(VariableMoveToComponent);
  }

  update(entity: ecs.Entity) {
    try {
      let move = entity.get(MoveToComp);
      let mtv = entity.get(VariableMoveToComponent);
      let end: Vec3;

      if (move.target instanceof Node) {
        end = move.ns === Node.NodeSpace.WORLD ? move.target.worldPosition : move.target.position;
      } else {
        end = move.target as Vec3;
      }
      // 目标移动后，重计算移动方向与移动到目标点的速度
      if (mtv.end === null || !mtv.end.strictEquals(end)) {
        let target = end.clone();
        if (move.offsetVector) {
          target = target.add(move.offsetVector); // 这里的问题
        }

        // 移动方向与移动数度
        let start = move.ns == Node.NodeSpace.WORLD ? move.node.worldPosition : move.node.position;
        move.velocity = Vec3Util.sub(target, start).normalize();

        // 移动时间与目标偏位置计算
        let distance = Vec3.distance(start, target) - move.offset;

        move.onChange?.call(this);

        if (distance - move.offset <= 0) {
          this.exit(entity);
        } else {
          mtv.timer.step = distance / move.speedOfMove;
          mtv.end = end.clone();
          mtv.target = move.velocity.clone().multiplyScalar(distance).add(start);
        }
      }

      if (move.speedOfMove > 0) {
        let trans = Vec3Util.mul(move.velocity, move.speedOfMove * this.dt);
        move.node.translate(trans, Node.NodeSpace.LOCAL);
      }

      let complete = mtv.timer.update(this.dt);
      // 移动完成事件
      if (complete) {
        if (move.ns == Node.NodeSpace.WORLD) move.node.worldPosition = mtv.target;
        else move.node.position = mtv.target;

        this.exit(entity);
      }
    } catch (error) {
      console.log(error, entity);
    }
  }

  private exit(e: ecs.Entity) {
    let move = e.get(MoveToComp);
    if (move.node.name === 'arrow-bullet1') {
      console.log('移动完成事件触发');
    }
    move.onComplete?.call(this);
    e.remove(VariableMoveToComponent);
    e.remove(MoveToComp);
  }
}
